#include "StdAfx.h"

#include "Common/String/StringConvert.h"

#include "Common/System/Clipboard.h"

#include "../Explorer/ContextMenu.h"

#include "App.h"
#include "Common/Lang/LangUtils.h"


using namespace Common;

LONG g_DllRefCount = 0;

static const UINT kSevenZipStartMenuID = kPluginMenuStartID ;
static const UINT kSystemStartMenuID = kPluginMenuStartID + 100;


void CPanel::Properties()
{
	std::vector<UINT32> operatedIndices;
	GetOperatedItemIndices(operatedIndices);
	m_directory.GetProperties(operatedIndices);
}

void CPanel::EditCut()
{
	// InvokeSystemCommand("cut");
}

void CPanel::EditCopy()
{

	CString s;
	std::vector<UINT32> indices;
	GetSelectedItemsIndices(indices);
	for (size_t i = 0; i < indices.size(); i++)
	{
		if (i > 0)
		{
			s += _T("\xD\n");
		}
		s += m_directory.GetItemName(indices[i]);
	}
	System::ClipboardSetText(_mainWindow, s);
}

void CPanel::EditPaste()
{

}

void CPanel::CreateSystemMenu(HMENU menuSpec,
							  const std::vector<UINT32> &operatedIndices,
							  CComPtr<IContextMenu> &systemContextMenu)
{
	systemContextMenu.Release();

	m_directory.CreateShellContextMenu(operatedIndices, systemContextMenu);

	if (systemContextMenu == 0)
	{
		return;
	}

	// Set up a CMINVOKECOMMANDINFO structure.
	CMINVOKECOMMANDINFO ci;
	ZeroMemory(&ci, sizeof(ci));
	ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
	ci.hwnd = GetParent();

	CMenuHandle popupMenu;
	if(!popupMenu.CreatePopupMenu())
	{
		throw 210503;
	}

	HMENU hMenu = popupMenu;

	DWORD Flags = CMF_EXPLORE;
	// Optionally the shell will show the extended
	// context menu on some operating systems when
	// the shift key is held down at the time the
	// context menu is invoked. The following is
	// commented out but you can uncommnent this
	// line to show the extended context menu.
	// Flags |= 0x00000080;
	systemContextMenu->QueryContextMenu(hMenu, 0, kSystemStartMenuID, 0x7FFF, Flags);


	CMenuHandle menu;
	menu.Attach(menuSpec);
	CMenuItemString menuItem;
	menuItem.fMask |= MIIM_SUBMENU | MIIM_ID;
	menuItem.hSubMenu = popupMenu;
	CString value(Lang::LangString(IDS_SYSTEM, 0x030202A0));
	menuItem.SetValue(value);
	menu.InsertMenuItem(0, TRUE, &menuItem);
}

void CPanel::CreateFileMenu(HMENU menuSpec)
{
	CreateFileMenu(menuSpec, _sevenZipContextMenu, _systemContextMenu, true);
}

void CPanel::CreateSevenZipMenu(HMENU menuSpec,
								const std::vector<UINT32> &operatedIndices,
								CComPtr<IContextMenu> &sevenZipContextMenu)
{
	sevenZipContextMenu.Release();

	bool sevenZipMenuCreated = false;

	CZipContextMenu* contextMenuSpec = new CComObject<CZipContextMenu>;
	contextMenuSpec->FinalConstruct();
	CComPtr<IContextMenu> contextMenu = contextMenuSpec;

	CString currentFolderUnicode = m_directory.GetCurrentDirectory();
	CStringVector names;
	size_t i;
	for(i = 0; i < operatedIndices.size(); i++)
	{
		names.push_back(currentFolderUnicode + m_directory.GetItemRelPath(operatedIndices[i]));
	}
	std::vector<const wchar_t*> namePointers;
	for(i = 0; i < operatedIndices.size(); i++)
	{
		namePointers.push_back(names[i]);
	}

	if (!operatedIndices.empty() && contextMenuSpec->InitContextMenu(currentFolderUnicode, &namePointers.front(),
			operatedIndices.size()) == S_OK)
	{
		HRESULT res = contextMenu->QueryContextMenu(menuSpec, 0, kSevenZipStartMenuID,
					  kSystemStartMenuID - 1, 0);
		sevenZipMenuCreated = (HRESULT_SEVERITY(res) == SEVERITY_SUCCESS);
		if (sevenZipMenuCreated)
		{
			sevenZipContextMenu = contextMenu;
		}
	}
}

void CPanel::CreateFileMenu(HMENU menuSpec,
							CComPtr<IContextMenu> &sevenZipContextMenu,
							CComPtr<IContextMenu> &systemContextMenu,
							bool programMenu)
{
	sevenZipContextMenu.Release();
	systemContextMenu.Release();

	std::vector<UINT32> operatedIndices;
	GetOperatedItemIndices(operatedIndices);

	CreateSevenZipMenu(menuSpec, operatedIndices, sevenZipContextMenu);
	if (g_App.ShowSystemMenu)
	{
		CreateSystemMenu(menuSpec, operatedIndices, systemContextMenu);
	}


	size_t i;
	for (i = 0; i < operatedIndices.size(); i++)
		if (m_directory.IsItemFolder(operatedIndices[i]))
		{
			break;
		}
	bool allAreFiles = (i == operatedIndices.size());
	LoadFileMenu(menuSpec, ::GetMenuItemCount(menuSpec), programMenu,
				 m_directory.IsFSFolder(), operatedIndices.size(), allAreFiles);
}

bool CPanel::InvokePluginCommand(int id)
{
	return InvokePluginCommand(id, _sevenZipContextMenu, _systemContextMenu);
}

bool CPanel::InvokePluginCommand(int id,
								 IContextMenu* sevenZipContextMenu, IContextMenu* systemContextMenu)
{
	UINT32 offset;
	bool isSystemMenu = (id >= kSystemStartMenuID);
	if (isSystemMenu)
	{
		offset = id  - kSystemStartMenuID;
	}
	else
	{
		offset = id  - kSevenZipStartMenuID;
	}

#ifdef UNDER_CE
	CMINVOKECOMMANDINFO
#else
	CMINVOKECOMMANDINFOEX
#endif
	commandInfo;
	commandInfo.cbSize = sizeof(commandInfo);
	commandInfo.fMask = 0
#ifndef UNDER_CE
						| CMIC_MASK_UNICODE
#endif
						;
	commandInfo.hwnd = GetParent();
	commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset));
	commandInfo.lpParameters = NULL;
	CString currentFolderSys = String::GetSystemString(m_directory.GetCurrentDirectory());
	commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys);
	commandInfo.nShow = SW_SHOW;
	commandInfo.lpParameters = NULL;
#ifndef UNDER_CE
	commandInfo.lpTitle = "";
	commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset));
	CString currentFolderUnicode = m_directory.GetCurrentDirectory();
	commandInfo.lpDirectoryW = currentFolderUnicode;
	commandInfo.lpTitleW = L"";
	commandInfo.ptInvoke.x = 0;
	commandInfo.ptInvoke.y = 0;
#endif
	HRESULT result;
	if (isSystemMenu)
	{
		result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));
	}
	else
	{
		result = sevenZipContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));
	}
	if (result == NOERROR)
	{
		KillSelection();
		return true;
	}
	return false;
}

void CPanel::OnContextMenu(CWindow wnd, CPoint point)
{
	if (wnd.GetParent() == _listView)
	{
		ShowColumnsContextMenu(point);
		return;
	}

	if (wnd != _listView)
	{
		return;
	}

	std::vector<UINT32> operatedIndices;
	GetOperatedItemIndices(operatedIndices);

	if (point.x < 0 || point.y < 0)
	{
		if (operatedIndices.size() == 0)
		{
			point.x = 0;
			point.y = 0;
		}
		else
		{
			int itemIndex = _listView.GetNextItem(-1, LVNI_FOCUSED);
			if (itemIndex == -1)
			{
				return ;
			}
			RECT rect;
			if (!_listView.GetItemRect(itemIndex, &rect, LVIR_ICON))
			{
				return ;
			}
			point.x = (rect.left + rect.right) / 2;
			point.y = (rect.top + rect.bottom) / 2;
		}
		_listView.ClientToScreen(&point);

	}

	CMenu menu;
	menu.CreatePopupMenu();

	CComPtr<IContextMenu> sevenZipContextMenu;
	CComPtr<IContextMenu> systemContextMenu;
	CreateFileMenu(menu, sevenZipContextMenu, systemContextMenu, false);

	//int result = menu.Track(TPM_LEFTALIGN
	int result = menu.TrackPopupMenu(TPM_LEFTALIGN
#ifndef UNDER_CE
									 | TPM_RIGHTBUTTON
#endif
									 | TPM_RETURNCMD | TPM_NONOTIFY,
									 point.x, point.y, _listView);

	if (result == 0)
	{
		return ;
	}

	if (result >= kPluginMenuStartID)
	{
		InvokePluginCommand(result, sevenZipContextMenu, systemContextMenu);
		return ;
	}
	if (ExecuteFileCommand(result))
	{
		return ;
	}
	return ;
}
